/*
 *  modelanim.h
 *  EncodeTest
 *
 *  Created by terry franguiadakis on 5/7/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */
#pragma once
#include "bbmath.h"
#include <vector>
#include <map>

#include "AnimSys.h"

class Model;

class Anim 
{
public:
	static Anim* Create(ModelData::Anim*  i_anim);
	
    Anim(float i_duration)
    :m_duration(i_duration) {}
    bool IsDone() {
        return m_isDone;
    }
    virtual void Reset()
    {
        m_isDone = false;
        m_utime  = 0.0f;
        m_curtime = 0.0f;
    }
    virtual void Update(Model* i_targetModel, float idt);
protected:
    bool   m_isDone;
    float  m_duration;
    float  m_utime;
    float  m_curtime;
};

class AnimVec2 : public Anim
{
public:
    AnimVec2(Vector2f& i_from, Vector2f& i_to, float i_duration)
    :Anim(i_duration), m_from(i_from), m_to(i_to) {}
    virtual void Reset()
    {
        Anim::Reset();
        m_curval = m_from;
    }
protected:
    const Vector2f& getCurValue() const {
        return m_curval; }

    Vector2f m_from, m_to;
    Vector2f m_curval;
};

class AnimF : public Anim
{
public:
    AnimF(float i_from, float i_to, float i_duration)
    :m_from(i_from), m_to(i_to), Anim(i_duration){}
    
    virtual void Reset()
    {
        Anim::Reset();
        m_curval = m_from;
    }
protected:
    float getCurValue() const {
        return m_curval;}

    float m_from, m_to;
    float m_curval;
};

class AnimRot : public AnimF
{
public:
    void Update(Model* i_model, float i_dt);    
};

class AnimUV  : public AnimVec2
{
public:
    void Update(Model* i_model, float i_dt);
};

class AnimPos  : public AnimVec2
{
public:
    void Update(Model* i_model, float i_dt);
};

class AnimScale  : public AnimVec2
{
public:
    void Update(Model* i_model, float i_dt);
};

class AnimIndex  : public AnimF
{
    public:
        void Update(Model* i_model, float i_dt);
    protected:
    // BB (TEF) - fix this
  //      int getCurValue() const {
    //        return m_curval;}
private:
        
};

// ---------------------------------------------------------------------------

class Sequence
{
public:
    void Update(Model* i_targetModel, float dt);
	static Sequence* Create(ModelData::Sequence *i_sequence);
private:

    std::vector<Anim*> m_anims;
    std::vector<Anim*> m_activeanims;
};


class SequenceSet 
{
	public:
		void Update(Model* i_targetModel, float dt);
		void SetCurrentSequence(std::string& i_name);
	static SequenceSet* Create(const std::vector<ModelData::Sequence*> &i_sequence);
	private:
	std::map<std::string, Sequence*> m_animations;
    std::vector<Sequence*> m_activeanims;
    std::vector<Sequence*> m_inactiveanims;

 };


// ---------------------------------------------------------------------------
/* 
 class texture {
	u/v coords
 };
 
 class TextureAtlas {
 };
 */
// ---------------------------------------------------------------------------

class Model 
{
public:
    static Model* Create(const ModelData::Model& modeldata);
    void PlayAnim(const char* animName);
    void Update(float dt);
    void Draw();
    void SetUVOffset(const Vector2f& i_uv) {
        m_uvoffset = i_uv;    }
    void SetPos(const Vector2f & i_pos ) {
        m_pos = i_pos;    }
    void SetRot(const float i_rot) {
        m_rot = i_rot;
    }
	// atlas case
 /*   void SetAtlasIndex(int i_index) {
        m_index = i_index;
    } */
	void SetUVOffset(Vector2f& i_offset) {
		/* nop */
	}
    void SetScale( const Vector2f& i_scale) {
        m_scale = i_scale;
    }
private:
    std::map<std::string, Sequence*> m_animations;
    std::vector<Sequence*> m_activeanims;
    std::vector<Sequence*> m_inactiveanims;
    std::vector<Model*> m_children;
    
    Vector2f m_offset;
    Vector2f m_pos; 
    Vector2f m_scale;
    Vector2f m_uvoffset;
    float    m_rot;    
    int      m_atlasIndex;
};
